using System;
using System.Runtime.InteropServices;
using System.Net;

using DirectShowLib;
using DirectShowLib.Utils;


// Add a reference to IGlobalist.Net.Rtp.dll
// Classes used - RtpSession, RtpSender, RtpParticipant, RtpStream
using IGlobalist.Net.Rtp;


namespace IGlobalist
{
/// <summary> Summary description for MainForm. </summary>
internal class CaptureDesktop : IDisposable
{
    #region Member variables

    /// <summary> graph builder interface. </summary>
    private IFilterGraph2 m_FilterGraph = null;
    IMediaControl m_mediaCtrl = null;

    /// <summary> Set by async routine when it captures an image </summary>
    private bool m_bRunning = false;

#if DEBUG
    DsROTEntry m_rot = null;
#endif

    #endregion

    /// <summary> release everything. </summary>
    public void Dispose()
    {
        GC.SuppressFinalize(this);
        CloseInterfaces();
    }

    ~CaptureDesktop()
    {
        Dispose();
    }

    /// <summary>
    /// Create capture object
    /// </summary>
    /// <param name="iDeviceNum">Zero based index of capture device</param>
    /// <param name="szFileName">Output ASF file name</param>
    public CaptureDesktop(RtpSender rtpSender)
    {
        try
        {
            // Set up the capture graph
            SetupGraph(rtpSender);

            m_bRunning = false;
        }
        catch
        {
            Dispose();
            throw;
        }
    }


    // Start the capture graph
    public void Start()
    {
        if (!m_bRunning)
        {
            int hr = m_mediaCtrl.Run();
            Marshal.ThrowExceptionForHR(hr);

            m_bRunning = true;
        }
    }

    // Pause the capture graph.
    // Running the graph takes up a lot of resources.  Pause it when it
    // isn't needed.
    public void Pause()
    {
        if (m_bRunning)
        {
            IMediaControl mediaCtrl = m_FilterGraph as IMediaControl;

            int hr = mediaCtrl.Pause();
            Marshal.ThrowExceptionForHR(hr);

            m_bRunning = false;
        }
    }

    private void SetupGraph(RtpSender rtpSender)
    {
        int hr;
        IBaseFilter capFilter = Global.GetDesktopInput();
        IBaseFilter rtpFilter = null;
        IBaseFilter compressor = Global.GetVideoCompressor();
        RtpFilters.IRtpRenderer rtpRender = null;
        ICaptureGraphBuilder2 capGraph = null;

        // Get the graphbuilder object
        m_FilterGraph = (IFilterGraph2)new FilterGraph();

#if DEBUG
        m_rot = new DsROTEntry(m_FilterGraph);
#endif

        try
        {
            // Get the ICaptureGraphBuilder2
            capGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();

            // Start building the graph
            hr = capGraph.SetFiltergraph(m_FilterGraph);
            Marshal.ThrowExceptionForHR(hr);

            // Add the capture device to the graph
            hr = m_FilterGraph.AddFilter(capFilter, "Video input");
            Marshal.ThrowExceptionForHR(hr);

            //Guid categoryGuid = new Guid("33d9a760-90c8-11d0-bd43-00a0c911ce86");
            //compressor = FilterGraphTools.AddFilterByName((IGraphBuilder)m_FilterGraph, categoryGuid, "Microsoft Windows Media Video 9");

            hr = m_FilterGraph.AddFilter(compressor, "Compressor");
            Marshal.ThrowExceptionForHR(hr);

            Guid CLSID_RtpRenderer = new Guid("CC7CE9F7-0927-4be6-84E7-305C4E45D3E1");
            rtpRender = (RtpFilters.IRtpRenderer)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_RtpRenderer, true));
            rtpRender.Initialize(rtpSender);
            rtpFilter = (IBaseFilter)rtpRender;

            hr = m_FilterGraph.AddFilter(rtpFilter, "RtpRenderer");
            Marshal.ThrowExceptionForHR(hr);

            hr = capGraph.RenderStream(null, null, capFilter, compressor, rtpFilter);
            Marshal.ThrowExceptionForHR(hr);

            m_mediaCtrl = m_FilterGraph as IMediaControl;
        }
        catch (Exception ex)
        {
        }
        finally
        {
            if (rtpFilter != null)
            {
                Marshal.ReleaseComObject(rtpFilter);
                rtpFilter = null;
            }
            if (rtpRender != null)
            {
                Marshal.ReleaseComObject(rtpRender);
                rtpRender = null;
            }
            if (compressor != null)
            {
                Marshal.ReleaseComObject(compressor);
                compressor = null;
            }
            if (capFilter != null)
            {
                Marshal.ReleaseComObject(capFilter);
                capFilter = null;
            }
            if (capGraph != null)
            {
                Marshal.ReleaseComObject(capGraph);
                capGraph = null;
            }
        }
    }
   
    /// <summary> Shut down capture </summary>
    private void CloseInterfaces()
    {
        int hr;

        try
        {
            if (m_mediaCtrl != null)
            {
                // Stop the graph
                hr = m_mediaCtrl.Stop();
                m_bRunning = false;
            }
        }
        catch
        {
        }

#if DEBUG
        // Remove graph from the ROT
        if (m_rot != null)
        {
            m_rot.Dispose();
            m_rot = null;
        }
#endif

        if (m_FilterGraph != null)
        {
            Marshal.ReleaseComObject(m_FilterGraph);
            m_FilterGraph = null;
        }
    }
}

}